<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Shop\Controller;

use Admin\Data\Common;
use Admin\Entity\SelfLocation;
use Doctrine\ORM\EntityManager;
use Laminas\Mvc\I18n\Translator;
use Laminas\View\Model\JsonModel;
use Laminas\View\Model\ViewModel;
use Operation\Entity\UserCoupon;
use Sales\Entity\Order;
use Sales\Service\OrderDeliveryAddressManager;
use Sales\Service\OrderGoodsManager;
use Sales\Service\OrderManager;
use Sales\Service\OrderSelfLocationManager;
use Sales\Service\OrderStatusManager;
use Shop\Common\ShopCommon;
use Shop\Form\CheckoutForm;
use Shop\Form\OrderPaymentForm;
use User\Entity\Cart;
use User\Entity\User;
use User\Entity\UserAddress;
use User\Service\CartManager;

class CheckoutController extends HomeActionController
{
    private $translator;
    private $entityManager;
    private $cartManager;
    private $orderManager;
    private $orderDeliveryAddressManager;
    private $orderSelfLocationManager;
    private $orderGoodsManager;
    private $writeEntityManager;
    private $orderStatusManager;

    public function __construct(
        Translator      $translator,
        EntityManager   $entityManager,
        EntityManager   $writeEntityManager,
        CartManager     $cartManager,
        OrderManager    $orderManager,
        OrderDeliveryAddressManager $orderDeliveryAddressManager,
        OrderSelfLocationManager    $orderSelfLocationManager,
        OrderGoodsManager           $orderGoodsManager,
        OrderStatusManager          $orderStatusManager
    )
    {
        $this->translator   = $translator;
        $this->entityManager= $entityManager;
        $this->writeEntityManager = $writeEntityManager;
        $this->cartManager  = $cartManager;
        $this->orderManager = $orderManager;
        $this->orderDeliveryAddressManager  = $orderDeliveryAddressManager;
        $this->orderSelfLocationManager     = $orderSelfLocationManager;
        $this->orderGoodsManager = $orderGoodsManager;
        $this->orderStatusManager= $orderStatusManager;
    }

    /**
     * 结账页面
     * @return array|\Laminas\Http\Response|ViewModel
     */
    public function indexAction()
    {
        return $this->checkout();
    }

    /**
     * 直接购买
     * @return array|\Laminas\Http\Response|ViewModel
     */
    public function buyNowAction()
    {
        return $this->checkout('index',true);
    }

    /**
     * 订单提交完成，进行支付；如是货到付款的支付方式，则切换页面
     * @return array|\Laminas\Http\Response|ViewModel
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function checkoutCompleteAction()
    {
        $view = new ViewModel();

        $orderId    = (int) $this->params()->fromRoute('id', 0);
        $orderInfo  = $this->writeEntityManager->getRepository(Order::class)->findOneBy(['orderId' => $orderId, 'userId' => parent::$userId]);
        if($orderInfo == null) return $this->redirect()->toRoute('shop');

        $this->layout()->setVariable('titleName', $orderInfo->getPaymentType() == 'CashOnDelivery' ? $this->translator->translate('订单提交完成') : $this->translator->translate('订单支付'));

        if($orderInfo->getPaymentType() == 'CashOnDelivery') {//货到付款的订单提交页面
            $view->setTemplate('shop/checkout/checkout-complete-cash-on-delivery');
            return $view->setVariables(['orderInfo' => $orderInfo]);
        }

        //如果已经付款(在线支付)
        if ($orderInfo->getPaymentFinishTime()) {
            if (in_array($orderInfo->getPaymentCode(), ['Wxpay'])) return $this->redirect()->toRoute('shop-return', ['action' => 'orderPaymentReturn', 'id' => $orderInfo->getOrderId()]);
            else return $this->redirect()->toRoute('home-order', ['action' => 'orderInfo', 'id' => $orderInfo->getOrderId()]);
        }

        $returnUrl  = $this->url()->fromRoute('shop-return', ['action' => 'orderPaymentReturn', 'id' => $orderInfo->getOrderId()], ['force_canonical' => true]);
        $notifyUrl  = $this->url()->fromRoute('shop-notify', ['action' => 'orderPaymentNotify', 'id' => $orderInfo->getOrderId()], ['force_canonical' => true]);
        $cancelUrl  = $this->url()->fromRoute('home-order', [], ['force_canonical' => true]);
        $orderUrl   = $this->url()->fromRoute('home-order', ['action' => 'orderInfo', 'id' => $orderInfo->getOrderId()], ['force_canonical' => true]);
        //微信公众号支付时，返回获取code，进而获取openid，非支付返回
        $wxReturnUrl= $this->url()->fromRoute('shop-checkout', ['action' => 'checkoutComplete', 'id' => $orderInfo->getOrderId()], ['force_canonical' => true]);

        //微信内调起支付
        if(!empty($orderInfo->getPaymentCode()) && in_array($orderInfo->getPaymentCode(), ['Wxpay']) && $orderInfo->getPaymentType() == 'OnlinePay' && isset($_GET['code'])) {
            $payResult = ShopCommon::shopPaymentService($orderInfo->getPaymentCode())->orderPaymentTo(['returnUrl' => $returnUrl, 'notifyUrl' => $notifyUrl, 'cancelUrl' => $cancelUrl, 'orderUrl' => $orderUrl, 'wxReturnUrl' => $wxReturnUrl, 'orderInfo' => $orderInfo]);
            if (isset($payResult['type']) && $payResult['type'] == 'wechat') {
                $view->setTemplate('shop/checkout/wechat-pay');
                return $view->setVariables(['orderInfo' => $orderInfo, 'result' => $payResult['result']]);
            }
        }

        $paymentList = ShopCommon::shopPaymentList('true', $orderInfo->getCurrencyCode());
        $form = new OrderPaymentForm($paymentList, $this->entityManager);
        if($this->getRequest()->isPost()) {
            $data = $this->params()->fromPost();
            $form->setData($data);
            if ($form->isValid()) {
                $data = $form->getData();
                $paymentConfig = ShopCommon::shopPaymentConfig($data['paymentCode']);
                $this->orderManager->editOrder(['paymentCode' => $data['paymentCode'], 'paymentName' => $paymentConfig['paymentName']['content']], $orderInfo);

                $payResult = ShopCommon::shopPaymentService($data['paymentCode'])->orderPaymentTo(['returnUrl' => $returnUrl, 'notifyUrl' => $notifyUrl, 'cancelUrl' => $cancelUrl, 'orderUrl' => $orderUrl, 'wxReturnUrl' => $wxReturnUrl, 'orderInfo' => $orderInfo]);
                //扫码支付（PC）
                if (in_array($data['paymentCode'], ['Wxpay']) && isset($payResult['type']) && $payResult['type'] == 'scan') {
                    $view->setTemplate('shop/checkout/scan-pay');
                    return $view->setVariables(['orderInfo' => $orderInfo, 'result' => $payResult['result']]);
                }
                //其他支付
                return $payResult;
            }
        }

        return ['form' => $form, 'orderInfo' => $orderInfo, 'paymentList' => $paymentList];
    }

    /**
     * 将结账单独拿出来处理
     * @param string $checkoutTempFile
     * @param bool $buyNowStatus
     * @return \Laminas\Http\Response|ViewModel
     */
    private function checkout($checkoutTempFile = 'index', $buyNowStatus = false)
    {
        $this->layout()->setVariable('titleName', $this->translator->translate('结账'));

        $userInfo = $this->writeEntityManager->getRepository(User::class)->findOneBy(['userId' => parent::$userId]);

        $deliveryType = $this->params()->fromQuery('deliveryType', '');

        //商品配送不开启，则切换到到店自提
        $deliveryState = Common::readConfigFile('delivery')['deliveryState'];
        if($deliveryState != 1) $deliveryType = 'self-fetch';

        //购物车商品
        $cartGoodsList = $this->entityManager->getRepository(Cart::class)->shopCartGoodsList(parent::$userId, 1, $buyNowStatus);
        if($cartGoodsList == null) {
            $this->flashMessenger()->addWarningMessage($this->translator->translate('购物车内没有选中的商品!'));
            return $this->redirect()->toRoute('shop-cart');
        }

        //收货地址
        $addressInfo    = null;
        $addressId      = (int) $this->params()->fromQuery('addressId', 0);
        $userAddress    = $this->entityManager->getRepository(UserAddress::class)->findBy(['userId' => parent::$userId], ['addrDefault' => 'DESC', 'addressId' => 'ASC']);
        if($userAddress != null) {
            $addressInfo = $this->entityManager->getRepository(UserAddress::class)->findOneBy(['userId' => parent::$userId, 'addressId' => $addressId]);
            if($addressInfo == null) $addressInfo = $userAddress[0];
        }

        //自提点地址
        $selfFetchList  = $this->entityManager->getRepository(SelfLocation::class)->findBy(['locationState' => 1], ['locationSort' => 'ASC']);
        if($deliveryType == 'self-fetch' && $selfFetchList == null) return $this->redirect()->toRoute('shop-cart');

        $response = $this->getEventManager()->trigger('shop.checkout.one.post', $this,
            [
                'userId'        => parent::$userId,
                'userGroupId'   => parent::$userGroupId,
                'addressInfo'   => $addressInfo,
                'deliveryType'  => $deliveryType,
                'cartGoodsList' => $cartGoodsList,
                'userInfo'      => $userInfo,
                'postArray'     => $this->params()->fromPost()
            ]);
        $array = array_merge(['userAddress' => $userAddress, 'selfFetchList' => $selfFetchList, 'userInfo' => $userInfo], $response->last());

        //当选择了自提点取货，但是订单中全部为虚拟商品或者有虚拟商品，则返回结算页面，不能使用自提点取货
        if($deliveryType == 'self-fetch' && ($array['allGoodsVirtual'] || $array['haveGoodsVirtual'])) return $this->redirect()->toRoute('shop-checkout');

        $form = new CheckoutForm(parent::$userId, $this->entityManager, $deliveryType, $array['allGoodsVirtual'], $array['haveGoodsVirtual']);
        if($this->getRequest()->isPost()) {
            $data = $this->params()->fromPost();
            $form->setData($data);
            if ($form->isValid()) {
                //配送方式内没有对应的匹配
                if(!$array['allGoodsVirtual'] && $deliveryType != 'self-fetch' && !$array['deliveryExist']) {
                    $this->flashMessenger()->addWarningMessage($this->translator->translate('请选择正确的配送方式!'));
                    return $this->shopPlugin()->toReferer();
                }

                $data = $form->getData();
                $data['userId']     = parent::$userId;
                $data['userName']   = parent::$userName;
                $data['orderAmount']= $array['orderAmount'];
                $data['goodsAmount']= $array['cartAmount'];
                $data['deliveryFee']= $array['deliveryFee'];
                $data['totalWeight']= $array['totalWeight'];

                $defaultCurrency = $this->shopPlugin()->getShopDefaultCurrency();
                $this->writeEntityManager->beginTransaction();
                try {
                    $orderInfo = $this->orderManager->addOrder($data, $defaultCurrency);
                    if(!$array['allGoodsVirtual']) {//当订单商品不全是虚拟商品时，可以添加线下配送
                        if($deliveryType == 'self-fetch') $this->orderSelfLocationManager->addOrderSelfLocation($data['locationId'], $orderInfo->getOrderId());
                        else $this->orderDeliveryAddressManager->addOrderDeliveryAddress($data, $orderInfo->getOrderId());
                    }
                    $cartIdArray = $this->orderGoodsManager->addOrderGoods($array['cartGoodsList'], $defaultCurrency, $orderInfo);
                    $this->cartManager->deleteCart($cartIdArray, $orderInfo->getUserId(), $buyNowStatus);
                    $this->orderStatusManager->addOrderStatus(['orderStatus' => $orderInfo->getOrderStatus(), 'operateUser' => self::$userName, 'orderId' => $orderInfo->getOrderId(), 'statusInfo' => $this->translator->translate('订单提交'), 'statusTime' => time()]);
                    $this->getEventManager()->trigger('shop.checkout.two.post', $this, ['orderInfo' => $orderInfo, 'array' => $array, 'defaultCurrency' => $defaultCurrency]);
                    $this->writeEntityManager->commit();

                    return $this->redirect()->toRoute('shop-checkout', ['action' => 'checkoutComplete', 'id' => $orderInfo->getOrderId()]);
                } catch (\Exception $e) {
                    $this->writeEntityManager->rollback();
                }
            }
        }

        $array['form'] = $form;
        $array['addressInfo']   = $addressInfo;
        $array['buyNowStatus']  = $buyNowStatus;
        $array['deliveryState'] = $deliveryState;
        $array['cashOnDelivery'] = Common::getPaymentConfig('CashOnDelivery');   //货到付款

        $view = new ViewModel();
        if($deliveryType == 'self-fetch') {//自提页面
            $view->setTemplate('shop/checkout/index-self-fetch');
            return $view->setVariables($array);
        }

        //送货时间
        $array['shippingDate'] = ShopCommon::shopShippingDate();

        $view->setTemplate('shop/checkout/'.$checkoutTempFile);
        return $view->setVariables($array);
    }

    /**
     * 优惠、积分、优惠券等调用
     * @return JsonModel
     */
    public function checkBuyGoodsUseAction()
    {
       $buyNowStatus    = $this->params()->fromQuery('buyNowStatus', 0);
       $useIntegralNum  = (int) $this->params()->fromPost('useIntegralNum', 0);
       $couponId        = (int) $this->params()->fromPost('couponId', 0);

        $userInfo = $this->writeEntityManager->getRepository(User::class)->findOneBy(['userId' => parent::$userId]);

        $deliveryType = $this->params()->fromQuery('deliveryType', '');

        //收货地址
        $addressInfo    = null;
        $addressId      = (int) $this->params()->fromQuery('addressId', 0);
        $userAddress    = $this->entityManager->getRepository(UserAddress::class)->findBy(['userId' => parent::$userId], ['addrDefault' => 'DESC', 'addressId' => 'ASC']);
        if($userAddress != null) {
            $addressInfo = $this->entityManager->getRepository(UserAddress::class)->findOneBy(['userId' => parent::$userId, 'addressId' => $addressId]);
            if($addressInfo == null) $addressInfo = $userAddress[0];
        }

        //购物车商品
        $cartGoodsList = $this->entityManager->getRepository(Cart::class)->shopCartGoodsList(parent::$userId, 1, $buyNowStatus);
        if($cartGoodsList == null) return new JsonModel(['status' => 'false', 'message' => $this->translator->translate('没有可购买的商品!')]);

        $response   = $this->getEventManager()->trigger('shop.checkout.one.post', $this, ['userId' => parent::$userId, 'userGroupId' => parent::$userGroupId, 'addressInfo' => $addressInfo, 'deliveryType' => $deliveryType, 'cartGoodsList' => $cartGoodsList]);
        $data       = $response->last();
        $orderAmount= $data['orderAmount'];

        //积分优惠
        $integralPrice = 0;
        if ($useIntegralNum > 0) {
            if ($userInfo->getIntegralType1Num() <= 0 || $useIntegralNum > $userInfo->getIntegralType1Num()) return new JsonModel(['status' => 'false', 'message' => $this->translator->translate('积分数量不可用!')]);
            if ($useIntegralNum > $data['goodsIntegralBuy']) return new JsonModel(['status' => 'false', 'message' => $this->translator->translate('积分超过可用值!')]);

            $integralPrice  = $useIntegralNum/Common::configValue('integral_type_1', 'integral')['integralCurrencyCon']/100;
            $orderAmount    = $orderAmount - $integralPrice;
            if ($orderAmount < 0)  return new JsonModel(['status' => 'false', 'message' => $this->translator->translate('积分超过可用值!')]);
        }

        //优惠券
        $couponPrice = 0;
        if ($couponId > 0) {
            $userCouponInfo = $this->entityManager->getRepository(UserCoupon::class)->findOneBy(['couponId' => $couponId, 'userId' => parent::$userId, 'couponUseState' => 1]);
            if ($userCouponInfo && !empty($data['couponPriceArray']) && isset($data['couponPriceArray'][$couponId]) && $data['couponPriceArray'][$couponId] > 0) {
                $couponPrice = $data['couponPriceArray'][$couponId];
                $orderAmount = $orderAmount - $couponPrice;
                if ($orderAmount < 0) return new JsonModel(['status' => 'false', 'message' => $this->translator->translate('优惠券优惠超过订单金额!')]);
            }
        }

        return new JsonModel([
            'status'        => 'true',
            'message'       => $this->translator->translate('处理完成'),

            'integralPrice' => '-' . $this->shopPlugin()->shopCurrency($integralPrice),
            'couponPrice'   => '-' . $this->shopPlugin()->shopCurrency($couponPrice),
            'orderAmount'   => $this->shopPlugin()->shopCurrency($orderAmount)


        ]);
    }
}